package com.example.aop;

import com.alibaba.fastjson.JSONObject;
import com.example.utils.IpUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * 业务聚合
 *
 * @version [V2.0]
 * @package com.ascpetj;
 * @description:[用一句话描述该文件做什么]
 * @author: [zhuben]
 * @date: [2024-02-01 17:03]
 * @copyright: 2024 echovin.com
 */

@Aspect
@Component
public class LogAop {
    private static final Logger log = LoggerFactory.getLogger(LogAop.class);

    // 配置织入点
    @Pointcut(value = "execution(* com.example.controller.*.*(..))")
    public void logPointCut(){
    }

    /**
     * 处理完请求后执行
     *
     * @param joinPoint 切点
     */
    @AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")
    public void doAfterReturning(JoinPoint joinPoint, Object jsonResult)
    {
        handleLog(joinPoint, null, jsonResult);
    }

    /**
     * 拦截异常操作
     *
     * @param joinPoint 切点
     * @param e 异常
     */
    @AfterThrowing(value = "logPointCut()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Exception e)
    {
        handleLog(joinPoint, e, null);
    }

    protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult)
    {
        try
        {
            long startTime = System.currentTimeMillis();
            //使用ServletRequestAttributes请求上下文获取方法更多
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            String method = request.getMethod();
            String className = joinPoint.getSignature().getDeclaringTypeName();
            Signature signature = joinPoint.getSignature();
            String name = signature.getName();
            //获取参数
            ObjectMapper mapper = new ObjectMapper();
            if (HttpMethod.GET.name().equals(method)){
                Enumeration<String> parameterNames = request.getParameterNames();
                Map<String, String> parameters = new HashMap<>();
                while (parameterNames.hasMoreElements()){
                    String param = parameterNames.nextElement();
                    String value = request.getParameter(param);
                    parameters.put(param, value);
                }
                log.info("调用前：{}.{}：{},传递的参数为：{}", className, name, method, JSONObject.toJSONString(parameters));
            }else{
                Object[] array = joinPoint.getArgs();
                log.info("调用前：{}.{}：{},传递的参数为：{}", className, name, method, mapper.writeValueAsString(array));
            }

            log.info("URL:{}", request.getRequestURL().toString());
            log.info("IP地址：{}", IpUtils.getIpAddr(request));
            //执行函数后打印日志

            log.info("调用后：{}.{}：{},返回值为：{},异常：{}", className, name, method, mapper.writeValueAsString(jsonResult), e);
            log.info("耗时：{}ms", System.currentTimeMillis() - startTime);
            //TODO 异步入库
        }
        catch (Exception exp)
        {
            // 记录本地异常日志
            log.error("==前置通知异常==");
            log.error("异常信息:{}", exp.getMessage());
            exp.printStackTrace();
        }
    }
}
